/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.click.app.webapp.action;

import com.click.app.Constants;
import com.click.app.model.Catalog;
import com.click.app.model.Category;
import com.click.app.model.User;
import com.click.app.service.UserExistsException;
import com.click.app.service.UserManager;
import com.click.app.webapp.util.RequestUtil;
import com.opensymphony.xwork2.Preparable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.directwebremoting.extend.AccessDeniedException;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.mail.MailException;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationTrustResolver;
import org.springframework.security.AuthenticationTrustResolverImpl;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.encoding.PasswordEncoder;

/**
 *
 * @author ariel
 */
public class UsersAction extends BaseAction implements Preparable {

    private List<User> users;
    private User user;
    private Long id;
    private Integer phoneIndex;
    private List<Category> listCategories;

    public void setId(Long id) {
        this.id = id;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Integer getPhoneIndex() {
        return phoneIndex;
    }

    public void setPhoneIndex(Integer phoneIndex) {
        this.phoneIndex = phoneIndex;
    }

    public String refreshPhoneList() {
        System.out.println("refreshing phones...");
        //       phoneList = (List<Phone>) getSession().getAttribute("phoneList");

        return SUCCESS;
    }

        /**
     * Grab the entity from the database before populating with request parameters
     */
    public void prepare() {
        if (getRequest().getMethod().equalsIgnoreCase("post")) {
            // prevent failures on new
            if (!"".equals(getRequest().getParameter("user.id"))) {
                user = userManager.getUser(getRequest().getParameter("user.id"));
            }
        }
    }
    /*
    public String deletePhone() {
    System.out.println("deleting Phone: " + phoneIndex + "...");

    phoneList = (List<Phone>) getSession().getAttribute("phoneList");

    phone = phoneList.get(phoneIndex);

    if (phone.getId() != null) {
    List<Phone> deletePhoneList = (List<Phone>) getSession().getAttribute("deletePhoneList");
    deletePhoneList.add(phone);
    getSession().setAttribute("deletePhoneList", deletePhoneList);
    }

    phoneList.remove(phone);

    getSession().setAttribute("phoneList", phoneList);

    phone = new Phone();
    phoneIndex = null;

    return SUCCESS;
    }
     */

    public String savePhone() {

        System.out.println("saving Phone...");

//        phoneList = (List<Phone>) getSession().getAttribute("phoneList");

        if (phoneIndex == null) {
            //          phoneList.add(phone);
        } else {
            //     phoneList.set(phoneIndex, phone);
            phoneIndex = null;
        }

        //      getSession().setAttribute("phoneList", phoneList);

        //      phone = new Phone();

        return SUCCESS;
    }

    public String delete() {
        System.out.println("deleting User...");

        userManager.removeUser(user.getId().toString());
        saveMessage(getText("user.deleted"));

        getSession().removeAttribute("phoneList");
        getSession().removeAttribute("deletePhoneList");

        return SUCCESS;
    }
    private PasswordEncoder passwordEncoder;

    @Required
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }
    public String listCatalog() {
        System.out.println("PortalAction -> listCatalog()");
        if (getRequest().getRemoteUser() != null) {
            User u = userManager.getUserByUsername(getRequest().getRemoteUser());
            getRequest().setAttribute("currentRole", u.getRoles().size());
        }
        System.out.println("catalogmanager: " + catalogManager);
        Catalog catalog = catalogManager.findCurrentCatalog();
        if (catalog != null) {
            setListCategories(catalog.getCategorys());
        } else {
            setListCategories(new ArrayList<Category>());
        }
        for (Category category : getListCategories()) {
            System.out.println(category);
//            for (Product p : category.getProducts()) {
        //              System.out.println("\t" + p);
        //        }
        }
        System.out.println("PortalAction -> end listCatalog()");
        return SUCCESS;
    }

    public String edit() throws IOException {
        HttpServletRequest request = getRequest();
        boolean editProfile = (request.getRequestURI().indexOf("editProfile") > -1);
        // if URL is "editProfile" - make sure it's the current user
        if (editProfile) {
            // reject if id passed in or "list" parameter passed in
            // someone that is trying this probably knows the AppFuse code
            // but it's a legitimate bug, so I'll fix it. ;-)
            if ((request.getParameter("id") != null) || (request.getParameter("from") != null)) {
                ServletActionContext.getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
                log.warn("User '" + request.getRemoteUser() + "' is trying to edit user '" + request.getParameter("id") + "'");

                return null;
            }
        }

        // if a user's id is passed in
        if (id != null) {
            try {
                Long.parseLong(id.toString());
                System.out.println("parsed: " + Long.parseLong(id.toString()));
                user = userManager.getUser(id.toString());
            } catch (Exception e) {
                user = userManager.getUserByUsername(id.toString());

            }
            // lookup the user using that id
            user = userManager.getUser(id.toString());
        } else if (editProfile) {
            user = userManager.getUserByUsername(request.getRemoteUser());
        } else {
            user = new User();
        // user.addRole(new Role(Constants.USER_ROLE));
        }

        if (user.getUsername() != null) {

            user.setConfirmPassword(user.getPassword());
            // if user logged in with remember me, display a warning that they can't change passwords
            log.debug("checking for remember me login...");

            AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
            SecurityContext ctx = SecurityContextHolder.getContext();

            if (ctx != null) {
                Authentication auth = ctx.getAuthentication();

                if (resolver.isRememberMe(auth)) {
                    getSession().setAttribute("cookieLogin", "true");
                    saveMessage(getText("userProfile.cookieLogin"));
                }
            }
        }
        System.out.println(user.getUsername());
        return SUCCESS;
    }

    public boolean validationPasses() {
        boolean required = false;
        boolean result = true;
        if ((user.getUsername() == null) || (user.getUsername().matches(""))) {
            result = false;
            required = true;
        //errorMessage("Required field Username. ");
        }
        if ((user.getPassword() == null) || (user.getPassword().matches(""))) {
            result = false;
            required = true;
        //errorMessage("Required field Password. ");
        }
        if ((user.getConfirmPassword() == null) || (user.getConfirmPassword().matches(""))) {
            result = false;
            required = true;
        //errorMessage("Required field Confirm password. ");
        }

        if (!(user.getPassword().matches(user.getConfirmPassword())) && !(passwordEncoder.isPasswordValid(user.getConfirmPassword(), user.getPassword(), null))) {
            result = false;
            errorMessage("Passwords don't match.");
        }
        if ((user.getPasswordHint() == null) || (user.getPasswordHint().matches(""))) {
            result = false;
            required = true;
        // errorMessage("Required field Passwod hint. ");
        }
        if ((user.getEmail() == null) || (user.getEmail().matches(""))) {
            result = false;
            required = true;
        //errorMessage("Required field Email. ");
        }
        if ((user.getFirstName() == null) || (user.getFirstName().matches(""))) {
            result = false;
            required = true;
        // errorMessage("Required field First name. ");
        }
        if ((user.getLastName() == null) || (user.getLastName().matches(""))) {
            result = false;
            required = true;
        //errorMessage("Required field Last name. ");
        }

        if (required) {
            errorMessage("Please fill all the required fields. ");
        }
        return result;
    }

    public String save() throws Exception {
        Integer originalVersion = user.getVersion();

        boolean isNew = ("".equals(getRequest().getParameter("user.version")));
        // only attempt to change roles if user is admin
        // for other users, prepare() method will handle populating
        if (getRequest().isUserInRole(Constants.ADMIN_ROLE)) {
            user.getRoles().clear(); // APF-788: Removing roles from user doesn't work
            String[] userRoles = getRequest().getParameterValues("userRoles");
            for (int i = 0; userRoles != null && i < userRoles.length; i++) {
                String roleName = userRoles[i];
                user.addRole(roleManager.getRole(roleName));
            }
        }

        try {
            if (validationPasses()){
            userManager.saveUser(user);
            }else{
                return ERROR;
            }

            System.out.println("user: "+user.getFullName() +" - "+user.getPassword() +" - "+user.getConfirmPassword());
        } catch (AccessDeniedException ade) {
            // thrown by UserSecurityAdvice configured in aop:advisor userManagerSecurity
            log.warn(ade.getMessage());
            getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
            return null;
        } catch (UserExistsException e) {
            List<String> args = new ArrayList<String>();
            args.add(user.getUsername());
            args.add(user.getEmail());
            addActionError(getText("errors.existing.user", args));

            // reset the version # to what was passed in
            user.setVersion(originalVersion);
            // redisplay the unencrypted passwords
            user.setPassword(user.getConfirmPassword());
            return INPUT;
        }

        if (!"list".equals(from)) {
            // add success messages
            saveMessage(getText("user.saved"));
            return "portal";
        } else {
            // add success messages
            List<String> args = new ArrayList<String>();
            args.add(user.getFullName());
            if (isNew) {
                saveMessage(getText("user.added", args));
                // Send an account information e-mail
                mailMessage.setSubject(getText("signup.email.subject"));
                try {
                    sendUserMessage(user, getText("newuser.email.message", args),
                            RequestUtil.getAppURL(getRequest()));
                } catch (MailException me) {
                    addActionError(me.getCause().getLocalizedMessage());
                }
                return SUCCESS;
            } else {
                saveMessage(getText("user.updated.byAdmin", args));
                return SUCCESS;
            }
        }
    }

    @Override
    public String cancel() {
        getSession().removeAttribute("phoneList");
        getSession().removeAttribute("deletePhoneList");

        return CANCEL;
    }

    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }

    public List<User> getUsers() {
        return users;
    }

    public String list() {
        users = userManager.getAll(User.class);
        return SUCCESS;
    }

    public String help() {
        return SUCCESS;
    }

    public String helpList() {
        return SUCCESS;
    }

    /**
     * @return the listCategories
     */
    public List<Category> getListCategories() {
        return listCategories;
    }

    /**
     * @param listCategories the listCategories to set
     */
    public void setListCategories(List<Category> listCategories) {
        this.listCategories = listCategories;
    }
}
